package com.icow.wms.basic.utils;

import com.icow.wms.basic.domain.Lift;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("all")
@Slf4j
public class LiftHandler extends ChannelInboundHandlerAdapter {

    public static Map<String, Channel> IP_CHANNEL_MAP = new HashMap<>();

    public static Map<String, Lift> IP_LIFT_MAP = new HashMap<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Channel inChannel = ctx.channel();
        String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        //永远将最新的通道保存至MAP
        IP_CHANNEL_MAP.put(ip, inChannel);
        if (IP_LIFT_MAP.get(ip) == null) {
            IP_LIFT_MAP.put(ip, new Lift(ip));
        }
        log.info("lift client " + ctx.channel().remoteAddress() + " is active");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        IP_CHANNEL_MAP.remove(ip);
        ctx.close();
        log.info(ctx.channel().remoteAddress() + " inactive pipe close");
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        IP_CHANNEL_MAP.remove(ip);
        ctx.close();
        log.info(ctx.channel().remoteAddress() + " exception pipe close " + cause.getMessage());
        cause.printStackTrace();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = null;
        if (msg instanceof ByteBuf) {
            byteBuf = (ByteBuf) msg;
        }
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);

        log.info(Arrays.toString(bytes));
        String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        Lift lift = IP_LIFT_MAP.get(ip);
        if (lift == null) {
            log.info("door " + ip + " not online");
        }
        String liftReachCommand = lift.getLiftReachCommand();
        if (liftReachCommand == null) {
            log.info("liftReachCommand is null");
        } else if (lift.equals(bytes, lift.getBytesForLift(liftReachCommand))) {
            switch (lift.getFloor()) {
                case "1":
                    lift.setLiftReachOne(true);
                    break;
                case "2":
                    lift.setLiftReachTwo(true);
                    break;
                case "3":
                    lift.setLiftReachThree(true);
                    break;
                case "4":
                    lift.setLiftReachFour(true);
                    break;
                default:
                    log.info("lift reach floor error " + ip);
            }
            log.info("lift reach " + ip + " floor " + lift.getFloor() + " " + Arrays.toString(lift.getBytesForLift(liftReachCommand)));
        }
        //Manual recycling to prevent memory leakage;
        ReferenceCountUtil.release(byteBuf);
    }

    public static boolean sendMsg(String ip, byte[] bytes) {
        if (IP_CHANNEL_MAP.containsKey(ip)) {
            Channel channel = IP_CHANNEL_MAP.get(ip);
            channel.writeAndFlush(Unpooled.wrappedBuffer(bytes));
            //log.info("向 " + ip + " 发送数据 " + Arrays.toString(bytes));
            return true;
        }
        log.info("send error not online " + ip);
        return false;

    }
}
